package com.xbongbong.saas.analytical.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.AttrLenthConstant;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.OutstockErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SettleAccountErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.saas.analytical.SaasValidateAnalyticalService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.domain.entity.SettleAccountsEntity;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.dictionary.TransferNewStatusEnum;
import com.xbongbong.saas.help.AnalyticalHelp;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.help.SaasProductHelp;
import com.xbongbong.saas.help.SaveFormatHelp;
import com.xbongbong.saas.model.SettleAccountsModel;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.util.ValidateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @date 2021/07/15 17:15
 */
@Service("transferAnalyticalServiceImpl")
public class TransferValidateAnalyticalServiceImpl implements SaasValidateAnalyticalService {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(TransferValidateAnalyticalServiceImpl.class);
    
    @Resource
    private UserTeamHelp userTeamHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private SaasProductHelp saasProductHelp;
    @Resource
    private SettleAccountsModel settleAccountsModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private AnalyticalHelp analyticalHelp;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.TRANSFER.getCode());
    }

    @Override
    public void analyticalData(ValidateDataDTO validateDataDTO) throws XbbException {
        beforeSave(validateDataDTO);
        //没有负责团队的 单负责人
        userTeamHelp.checkPermissionOptionTeam(validateDataDTO);
    }
    
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        try {
            String corpid = validateDataDTO.getCorpid();
            JSONObject data = validateDataDTO.getData();
            Long taskId = validateDataDTO.getTaskId();
            //获取调拨单据日期
            Long transferTime=data.getLong(TransferEnum.TRANSFER_TIME.getAttr());
            //结账中校验
            String redisHelperValue = paasRedisHelper.getValue(RedisPrefixConstant.SETTLE_ACCOUNTS, corpid);
            if (StringUtil.isNotEmpty(redisHelperValue)) {
                if (transferTime <= DateTimeUtil.getTodayEndInt(Long.valueOf(redisHelperValue))) {
                    throw new XbbException(SettleAccountErrorCodeEnum.API_ERROR_254007);
                }
            }
            //结账内校验
            SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
            if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
                if (transferTime <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                    throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212051);
                }
            }
            // 初始化逻辑字段
            FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
            Map<String, FieldAttrEntity> explainMap = validateDataDTO.getExplainMap();
            FieldAttrEntity sheetNo = explainMap.getOrDefault(TransferEnum.SHEET_NO.getAttr(), fieldAttrEntity);
            FieldAttrEntity intoWarehouseIdField = explainMap.getOrDefault(TransferEnum.INTO_WAREHOUSE_ID.getAttr(), fieldAttrEntity);
            FieldAttrEntity outWarehouseIdField = explainMap.getOrDefault(TransferEnum.OUT_WAREHOUSE_ID.getAttr(), fieldAttrEntity);
            FieldAttrEntity memoField = explainMap.getOrDefault(TransferEnum.MEMO.getAttr(), fieldAttrEntity);
            FieldAttrEntity productField = explainMap.getOrDefault(TransferEnum.PRODUCTS.getAttr(), fieldAttrEntity);
            // 校验编号长度不超过100且编号存在
            if (Objects.nonNull(sheetNo) && Objects.equals(sheetNo.getStrictController(), BasicConstant.ZERO)) {
                ValidateUtil.checkSerialNumber(validateDataDTO.getSerialNo(), Objects.toString(sheetNo.getAttrName(), ""));
            }
            // 格式化关联的仓库
            SaveFormatHelp.formatLinkBusiness4Save(data, TransferEnum.OUT_WAREHOUSE_ID.getAttr(), TransferEnum.OUT_WAREHOUSE_ID_LINKED_TEXT.getAttr(), TransferEnum.OUT_WAREHOUSE_ID.getFieldType());
            SaveFormatHelp.formatLinkBusiness4Save(data, TransferEnum.INTO_WAREHOUSE_ID.getAttr(), TransferEnum.INTO_WAREHOUSE_ID_LINKED_TEXT.getAttr(), TransferEnum.INTO_WAREHOUSE_ID.getFieldType());
            // 校验调入仓库和调出仓库是否相同
            Long outWarehouseId = FastJsonHelper.getLongFromFormData(data, TransferEnum.OUT_WAREHOUSE_ID.getAttr());
            String outWarehouseName = FastJsonHelper.getStringOrDefaultFromFormData(data, TransferEnum.OUT_WAREHOUSE_ID_LINKED_TEXT.getAttr(), "");
            Long intoWarehouseId = FastJsonHelper.getLongFromFormData(data, TransferEnum.INTO_WAREHOUSE_ID.getAttr());
            if (Objects.equals(outWarehouseId, intoWarehouseId)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028.getCode(), ErrorMessageConstant.ATTR_SAME, Objects.toString(intoWarehouseIdField.getAttrName(), ""), Objects.toString(outWarehouseIdField.getAttrName(), ""));
            }
            // 校验备注长度
            ValidateUtil.checkFieldEntityLength(data, TransferEnum.MEMO.getAttr(), Objects.toString(memoField.getAttrName(), ""), AttrLenthConstant.MEMO_MAX_LENGTH);
            //批次号保存必填校验
            SaveFormatHelp.batchSaveRequiredCheck(validateDataDTO);
            JSONArray productArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,TransferEnum.PRODUCTS.getAttr(),new JSONArray());
            if (productArray == null || productArray.isEmpty()) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028.getCode(), ErrorMessageConstant.PLEASE_SELECT, Objects.toString(productField.getAttrName(), ""));
            }
            // 校验产品
            boolean isNew = analyticalHelp.isNew(validateDataDTO.getDataId(), taskId, validateDataDTO.getCorpid());
            Boolean productCanSee = true;
            if (!isNew) {
                productCanSee = commonHelp.attrCanSee(validateDataDTO.getExplainMap().get(TransferEnum.PRODUCTS.getAttr()),validateDataDTO.getDataId(),validateDataDTO.getCreatorId(),validateDataDTO.getLoginUser(),validateDataDTO.getCorpid(),XbbRefTypeEnum.TRANSFER.getCode());
            }
            boolean hasInOrOut = (Objects.nonNull(data.getInteger(TransferEnum.INSTOCK_ID.getAttr())) && !Objects.equals(data.getInteger(TransferEnum.INSTOCK_ID.getAttr()),0))
                    || (Objects.nonNull(data.get(TransferEnum.OUTSTOCK_ID.getAttr())) && !Objects.equals(data.getInteger(TransferEnum.OUTSTOCK_ID.getAttr()),0));
            if (isNew || (productCanSee && !hasInOrOut)){
                validateProduct(productArray,validateDataDTO.getCorpid(),outWarehouseId,outWarehouseName);
                data.put(TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.UNTRANSFORMED.getCode());
            }
            for (Map.Entry<String,Object> entry : SaasDataInitHelp.initTransfer().entrySet()){
                SaasDataInitHelp.antDataSet(data,entry.getKey(),entry.getValue());
            }
            Map<String,Boolean> attrCanSeeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            attrCanSeeMap.put(TransferEnum.PRODUCTS.getAttr(),productCanSee);
            SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo = new SaasNeedRedundantAttrPojo();
            saasNeedRedundantAttrPojo.setAttrCanSeeMap(attrCanSeeMap);
            validateDataDTO.setSaasNeedRedundantAttrPoJo(saasNeedRedundantAttrPojo);
            validateDataDTO.setData(data);
        } catch (XbbException e) {
            throw e;
        }  catch (Exception e) {
            LOGGER.error("transferAnalyticalServiceImpl.beforeSave error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private void validateProduct(JSONArray productArray, String corpid, Long outWarehouseId, String outWarehouseName) throws XbbException {
        Set<Long> pageProductIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,Double> productNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (Object object:productArray) {
            JSONObject jsonObject = (JSONObject) object;
            Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            pageProductIds.add(productId);
            Double productNum = jsonObject.getDouble(SelectProductEnum.NUM.getAttr());
            Double num = productNumMap.getOrDefault(productId,0D);
            num += productNum;
            productNumMap.put(productId,num);
        }
        saasProductHelp.productExit(corpid,new ArrayList<>(pageProductIds));
        saasProductHelp.warehouseProductNumLegalCheck(corpid,productArray,outWarehouseId,true, OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode());
    }
}
